import * as fs from 'fs';
import * as path from 'path';

export interface EnumExtractionResult {
  success: boolean;
  message: string;
  enumSuggestions: EnumSuggestion[];
  filesModified: string[];
  enumsCreated: string[];
  errors?: string[];
}

export interface EnumSuggestion {
  enumName: string;
  values: string[];
  locations: Array<{
    file: string;
    line: number;
    context: string;
  }>;
  suggestedEnumCode: string;
  confidence: 'high' | 'medium' | 'low';
}

export class EnumExtractor {
  
  /**
   * 分析并提取枚举建议
   */
  async analyzeForEnums(filePath: string, autoCreate: boolean = false): Promise<EnumExtractionResult> {
    const result: EnumExtractionResult = {
      success: false,
      message: '',
      enumSuggestions: [],
      filesModified: [],
      enumsCreated: [],
      errors: []
    };

    try {
      const content = fs.readFileSync(filePath, 'utf-8');
      const enumSuggestions = this.findEnumOpportunities(content, filePath);
      
      result.enumSuggestions = enumSuggestions;

      if (autoCreate && enumSuggestions.length > 0) {
        for (const suggestion of enumSuggestions) {
          if (suggestion.confidence === 'high') {
            await this.createEnumAndUpdateReferences(filePath, suggestion, result);
          }
        }
      }

      result.success = true;
      result.message = autoCreate 
        ? `创建了 ${result.enumsCreated.length} 个枚举类`
        : `发现 ${enumSuggestions.length} 个枚举提取机会`;

    } catch (error) {
      result.errors?.push(`枚举分析失败: ${error}`);
      result.message = `枚举分析失败: ${error}`;
    }

    return result;
  }

  private findEnumOpportunities(content: string, filePath: string): EnumSuggestion[] {
    const suggestions: EnumSuggestion[] = [];
    
    // 1. 查找字符串常量模式
    suggestions.push(...this.findStringConstantPatterns(content, filePath));
    
    // 2. 查找状态值模式
    suggestions.push(...this.findStatusPatterns(content, filePath));
    
    // 3. 查找类型标识符模式
    suggestions.push(...this.findTypeIdentifierPatterns(content, filePath));

    return suggestions;
  }

  private findStringConstantPatterns(content: string, filePath: string): EnumSuggestion[] {
    const suggestions: EnumSuggestion[] = [];
    const lines = content.split('\n');
    
    // 查找相关的字符串常量组
    const stringGroups = new Map<string, string[]>();
    
    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];
      const lineNumber = i + 1;
      
      // 匹配字符串比较：if (status.equals("ACTIVE"))
      const stringComparePattern = /(\w+)\.equals\(["']([^"']+)["']\)|["']([^"']+)["']\.equals\((\w+)\)/g;
      let match;
      
      while ((match = stringComparePattern.exec(line)) !== null) {
        const value = match[2] || match[3];
        const variable = match[1] || match[4];
        
        if (this.isPotentialEnumValue(value)) {
          if (!stringGroups.has(variable)) {
            stringGroups.set(variable, []);
          }
          stringGroups.get(variable)!.push(value);
        }
      }
      
      // 匹配switch语句中的字符串case
      const switchCasePattern = /case\s+["']([^"']+)["']\s*:/g;
      while ((match = switchCasePattern.exec(line)) !== null) {
        const value = match[1];
        if (this.isPotentialEnumValue(value)) {
          const contextVar = this.findSwitchVariable(lines, i);
          if (contextVar) {
            if (!stringGroups.has(contextVar)) {
              stringGroups.set(contextVar, []);
            }
            stringGroups.get(contextVar)!.push(value);
          }
        }
      }
    }

    // 生成枚举建议
    for (const [variable, values] of stringGroups) {
      if (values.length >= 2) {
        const uniqueValues = [...new Set(values)];
        const enumName = this.generateEnumName(variable);
        
        suggestions.push({
          enumName,
          values: uniqueValues,
          locations: this.findValueLocations(content, uniqueValues, filePath),
          suggestedEnumCode: this.generateEnumCode(enumName, uniqueValues),
          confidence: uniqueValues.length >= 3 ? 'high' : 'medium'
        });
      }
    }

    return suggestions;
  }

  private findStatusPatterns(content: string, filePath: string): EnumSuggestion[] {
    const suggestions: EnumSuggestion[] = [];
    
    // 常见的状态字段模式
    const statusPatterns = [
      /status\s*=\s*["']([^"']+)["']/gi,
      /state\s*=\s*["']([^"']+)["']/gi,
      /type\s*=\s*["']([^"']+)["']/gi,
      /mode\s*=\s*["']([^"']+)["']/gi,
      /level\s*=\s*["']([^"']+)["']/gi
    ];

    for (const pattern of statusPatterns) {
      const matches = [...content.matchAll(pattern)];
      if (matches.length >= 2) {
        const values = [...new Set(matches.map(m => m[1]))];
        const fieldName = pattern.source.split('\\s*=')[0];
        const enumName = this.generateEnumName(fieldName);
        
        suggestions.push({
          enumName,
          values,
          locations: this.findValueLocations(content, values, filePath),
          suggestedEnumCode: this.generateEnumCode(enumName, values),
          confidence: values.length >= 4 ? 'high' : 'medium'
        });
      }
    }

    return suggestions;
  }

  private findTypeIdentifierPatterns(content: string, filePath: string): EnumSuggestion[] {
    const suggestions: EnumSuggestion[] = [];
    
    // 查找数字常量模式（可能的枚举值）
    const numberConstantPattern = /(final\s+)?int\s+(\w+)\s*=\s*(\d+)\s*;/g;
    const numberConstants = new Map<string, number>();
    
    let match;
    while ((match = numberConstantPattern.exec(content)) !== null) {
      const name = match[2];
      const value = parseInt(match[3]);
      numberConstants.set(name, value);
    }

    // 如果有连续的数字常量，建议创建枚举
    if (numberConstants.size >= 3) {
      const sortedConstants = Array.from(numberConstants.entries())
        .sort((a, b) => a[1] - b[1]);
      
      // 检查是否是连续的或有规律的数字
      const isSequential = sortedConstants.every((entry, index) => 
        index === 0 || entry[1] === sortedConstants[index - 1][1] + 1
      );

      if (isSequential) {
        const enumName = this.generateEnumNameFromConstants(sortedConstants.map(c => c[0]));
        
        suggestions.push({
          enumName,
          values: sortedConstants.map(c => c[0]),
          locations: this.findConstantLocations(content, sortedConstants.map(c => c[0]), filePath),
          suggestedEnumCode: this.generateEnumCodeFromConstants(enumName, sortedConstants),
          confidence: 'high'
        });
      }
    }

    return suggestions;
  }

  private isPotentialEnumValue(value: string): boolean {
    // 检查是否看起来像枚举值
    return /^[A-Z][A-Z0-9_]*$/.test(value) || // 全大写
           /^[A-Za-z][A-Za-z0-9]*$/.test(value) && value.length > 2; // 有意义的字符串
  }

  private findSwitchVariable(lines: string[], currentIndex: number): string | null {
    // 向上查找switch语句
    for (let i = currentIndex; i >= 0; i--) {
      const switchMatch = lines[i].match(/switch\s*\(\s*(\w+)/);
      if (switchMatch) {
        return switchMatch[1];
      }
    }
    return null;
  }

  private generateEnumName(variable: string): string {
    // 将变量名转换为合适的枚举名
    return variable.charAt(0).toUpperCase() + variable.slice(1) + 'Enum';
  }

  private generateEnumNameFromConstants(constants: string[]): string {
    // 从常量名推断枚举名
    const commonPrefix = this.findCommonPrefix(constants);
    return commonPrefix ? commonPrefix.charAt(0).toUpperCase() + commonPrefix.slice(1).toLowerCase() + 'Type' : 'StatusType';
  }

  private findCommonPrefix(strings: string[]): string {
    if (strings.length === 0) return '';
    
    let prefix = strings[0];
    for (let i = 1; i < strings.length; i++) {
      while (prefix && !strings[i].startsWith(prefix)) {
        prefix = prefix.substring(0, prefix.length - 1);
      }
    }
    
    return prefix;
  }

  private generateEnumCode(enumName: string, values: string[]): string {
    const enumValues = values.map(v => `    ${v.toUpperCase()}`).join(',\n');
    
    return `public enum ${enumName} {
${enumValues};
    
    private final String value;
    
    ${enumName}(String value) {
        this.value = value;
    }
    
    public String getValue() {
        return value;
    }
    
    public static ${enumName} fromValue(String value) {
        for (${enumName} e : values()) {
            if (e.value.equals(value)) {
                return e;
            }
        }
        throw new IllegalArgumentException("Unknown value: " + value);
    }
}`;
  }

  private generateEnumCodeFromConstants(enumName: string, constants: Array<[string, number]>): string {
    const enumValues = constants.map(([name, value]) => `    ${name}(${value})`).join(',\n');
    
    return `public enum ${enumName} {
${enumValues};
    
    private final int value;
    
    ${enumName}(int value) {
        this.value = value;
    }
    
    public int getValue() {
        return value;
    }
    
    public static ${enumName} fromValue(int value) {
        for (${enumName} e : values()) {
            if (e.value == value) {
                return e;
            }
        }
        throw new IllegalArgumentException("Unknown value: " + value);
    }
}`;
  }

  private findValueLocations(content: string, values: string[], filePath: string): Array<{file: string, line: number, context: string}> {
    const locations: Array<{file: string, line: number, context: string}> = [];
    const lines = content.split('\n');
    
    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];
      for (const value of values) {
        if (line.includes(`"${value}"`) || line.includes(`'${value}'`)) {
          locations.push({
            file: filePath,
            line: i + 1,
            context: line.trim()
          });
        }
      }
    }
    
    return locations;
  }

  private findConstantLocations(content: string, constants: string[], filePath: string): Array<{file: string, line: number, context: string}> {
    const locations: Array<{file: string, line: number, context: string}> = [];
    const lines = content.split('\n');
    
    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];
      for (const constant of constants) {
        if (line.includes(constant)) {
          locations.push({
            file: filePath,
            line: i + 1,
            context: line.trim()
          });
        }
      }
    }
    
    return locations;
  }

  private async createEnumAndUpdateReferences(filePath: string, suggestion: EnumSuggestion, result: EnumExtractionResult): Promise<void> {
    // 创建枚举文件
    const dir = path.dirname(filePath);
    const enumFilePath = path.join(dir, `${suggestion.enumName}.java`);
    
    // 添加package声明（如果原文件有的话）
    const originalContent = fs.readFileSync(filePath, 'utf-8');
    const packageMatch = originalContent.match(/package\s+([^;]+);/);
    const packageDeclaration = packageMatch ? packageMatch[0] + '\n\n' : '';
    
    const enumContent = packageDeclaration + suggestion.suggestedEnumCode;
    
    fs.writeFileSync(enumFilePath, enumContent);
    result.enumsCreated.push(suggestion.enumName);
    result.filesModified.push(enumFilePath);
    
    // 更新原文件中的引用（简化版本）
    let modifiedContent = originalContent;
    
    // 添加import
    if (packageMatch) {
      modifiedContent = modifiedContent.replace(
        packageMatch[0],
        packageMatch[0] + `\nimport ${packageMatch[1].trim()}.${suggestion.enumName};`
      );
    }
    
    // 这里可以添加更复杂的引用替换逻辑
    
    fs.writeFileSync(filePath, modifiedContent);
    if (!result.filesModified.includes(filePath)) {
      result.filesModified.push(filePath);
    }
  }
}